<template>
    <div class="system-user" v-loading="isLoading">
        <!-- 组件文档请查阅: http://bearsee.com.cn/sibionics-ui-next -->
        <sib-tree filterable default-expand-all :props="treeProps" :request-config="treeRequestConfig" @node-click="nodeClick"></sib-tree>
        <sib-table
            row-key="deptId"
            ref="sibTableRef"
            :search-config="searchConfig"
            :table-column="tableColumn"
            :request-config="requestConfig">
            <!-- 自定义插槽，插槽名称为对应列配置的 code -->
            <template #operate="{ row }">
                <el-button type="primary" link @click="handleEdit(row)">修改</el-button>
                <el-button type="primary" link @click="handleReset(row)">重置</el-button>
                <el-button type="danger" link @click="handleDelete(row)">删除</el-button>
            </template>
            <!-- 自定义表单与列表之间的内容 -->
            <template #operation-container>
                <el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
                <sib-item :props="importProps"></sib-item>
                <el-button type="info" plain icon="Download" @click="handleDownload">下载模板</el-button>
                <el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
            </template>
        </sib-table>
        <el-dialog
            v-if="dialogConfig.visible"
            append-to-body
            draggable
            align-center
            v-model="dialogConfig.visible"
            :close-on-click-modal="false"
            :title="dialogConfig.title"
            :width="dialogConfig.width || '600px'">
            <sib-form v-bind="dialogConfig" :fields="dialogFields" @reset="dialogConfig.visible = false" @submit="handleSubmit"></sib-form>
        </el-dialog>
    </div>
</template>

<script>
import { ref, reactive, computed, inject } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';

export default {
    name: 'SystemUser',
    setup() {
        const axios = inject('$axios');
        const sibTableRef = ref(null);
        // 导出模板加载中遮罩
        const isLoading = ref(false);
        // 左侧部门树配置
        const treeProps = reactive({ label: 'label' });
        const treeRequestConfig = reactive({
            url: 'department-list.json',
            method: 'get',
        });
        // 查询模块表单配置
        const searchConfig = reactive({
            showExpand: false,
            rowFieldSize: 4,
            fields: [
                {
                    label: '用户名称',
                    code: 'userName',
                    type: 'text',
                    maxlength: 100,
                },
                {
                    label: '状态',
                    code: 'status',
                    type: 'select',
                    optionProps: { value: 'dictValue', label: 'dictLabel' },
                    requestConfig: {
                        url: 'common-status.json',
                        method: 'get',
                    },
                    options: [],
                },
                {
                    label: '创建时间',
                    code: 'daterange',
                    type: 'daterange',
                    startCode: 'beginTime',
                    endCode: 'endTime',
                    // 使用时间戳 valueFormat: 'x'
                    // valueFormat: 'x',
                },
            ],
        });
        // 表格表头配置
        const tableColumn = ref([
            {
                label: '用户名称',
                code: 'userName',
                minWidth: 100,
            },
            {
                label: '用户昵称',
                code: 'nickName',
                minWidth: 100,
            },
            {
                label: '部门',
                code: 'deptName',
                minWidth: 120,
            },
            {
                label: '手机号码',
                code: 'phonenumber',
                minWidth: 120,
            },
            {
                label: '状态',
                code: 'status',
                type: 'switch',
                activeValue: '0',
                inactiveValue: '1',
                beforeChange(value, { userId, userName }) {
                    return new Promise((resolve, reject) => {
                        const message = `确认要${value === '0' ? '启用' : '停用'}${userName}吗?`;
                        ElMessageBox.confirm(message).then(() => {
                            axios.put('/user/changeStatus', { status: value, userId }).then(() => {
                                resolve();
                                ElMessage.success('操作成功');
                            }).catch(reject);
                        }).catch(reject);
                    });
                },
            },
            {
                label: '创建时间',
                code: 'createTime',
                type: 'timeStamp',
                format: 'YYYY-MM-DD hh:mm',
                minWidth: 180,
            },
            {
                label: '操作',
                code: 'operate',
                type: 'slot',
                minWidth: 160,
                fixed: 'right',
            },
        ]);
        // 列表查询接口配置
        const requestConfig = reactive({
            url: 'user-list.json',
            method: 'get',
            params: {},
        });
        // 上传操作配置
        const importProps = reactive({
            type: 'upload',
            action: `${axios.defaults.baseURL}/user/importData`,
            showTips: false,
            showFileList: false,
            icon: 'Upload',
            headers: { Authorization: 'Bearer xxxxxxxx' },
            onSuccess: res => {
                if (res.code === 200) {
                    ElMessage.success('上传成功');
                    sibTableRef.value.getTableData();
                    return;
                }
                ElMessage.error(res.msg || '上传失败');
            },
            onError: () => {
                ElMessage.error('上传失败');
            },
        });

        const sibFormRef = ref(null);
        // 新增、编辑等弹窗配置
        const dialogConfig = reactive({
            title: '',
            width: '600px',
            rowFieldSize: 2,
            resetText: '取消',
            autoOperateBtnWidth: false,
            // add/edit/reset
            type: 'add',
            visible: false,
            form: {},
        });

        // 弹窗表单项配置
        const dialogFields = computed(() => {
            if (dialogConfig.type === 'reset') {
                return [
                    {
                        label: '新密码',
                        code: 'password',
                        type: 'password',
                        maxlength: 20,
                        required: true,
                        rules: [
                            { min: 8, max: 20, message: '长度在 8 到 20 个字符', trigger: 'change' },
                        ],
                    },
                ];
            }
            return [
                {
                    label: '用户昵称',
                    code: 'nickName',
                    type: 'text',
                    maxlength: 30,
                    required: true,
                },
                {
                    label: '归属部门',
                    code: 'deptId',
                    requestConfig: {
                        url: 'user-tree.json',
                        method: 'get',
                    },
                    /** 弹窗树形式 */
                    type: 'tree',
                    filterable: true,
                    optionProps: {
                        label: 'label',
                        value: 'id',
                    },
                    /** 级联形式 */
                    // type: 'cascader',
                    // options: [],
                    // optionProps: {
                    //     emitPath: false,
                    //     checkStrictly: true,
                    //     label: 'label',
                    //     value: 'id',
                    // },
                },
                {
                    label: '手机号码',
                    code: 'phonenumber',
                    type: 'text',
                    valueType: 'number',
                    maxlength: 11,
                },
                {
                    label: '邮箱',
                    code: 'email',
                    type: 'text',
                    maxlength: 50,
                },
                {
                    label: '用户名称',
                    code: 'userName',
                    type: 'text',
                    maxlength: 20,
                    rules: [{ min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' }],
                    required: true,
                    show: dialogConfig.type === 'add',
                },
                {
                    label: '用户密码',
                    code: 'password',
                    type: 'password',
                    maxlength: 20,
                    rules: [
                        { min: 8, max: 20, message: '长度在 8 到 20 个字符', trigger: 'blur' },
                    ],
                    required: true,
                    show: dialogConfig.type === 'add',
                },
                {
                    label: '用户性别',
                    code: 'sex',
                    type: 'select',
                    options: [
                        { label: '男', value: '1' },
                        { label: '女', value: '2' },
                    ],
                },
                {
                    label: '状态',
                    code: 'status',
                    type: 'radio',
                    options: [],
                    optionProps: {
                        label: 'dictLabel',
                        value: 'dictValue',
                    },
                    requestConfig: {
                        url: 'common-status.json',
                        method: 'get',
                    },
                    value: '0',
                },
                {
                    label: '岗位',
                    code: 'postIds',
                    type: 'select',
                    multiple: true,
                    options: [],
                },
                {
                    label: '角色',
                    code: 'roleIds',
                    type: 'select',
                    multiple: true,
                },
                {
                    label: '备注',
                    code: 'remark',
                    type: 'textarea',
                    width: '100%',
                },
            ];
        });

        return {
            isLoading,
            sibTableRef,
            treeProps,
            treeRequestConfig,
            searchConfig,
            tableColumn,
            requestConfig,
            importProps,
            dialogConfig,
            dialogFields,
            sibFormRef,
            nodeClick(data) {
                requestConfig.params.deptId = data.id;
            },
            handleReset({ userId }) {
                Object.assign(dialogConfig, {
                    title: '重置密码',
                    type: 'reset',
                    rowFieldSize: 1,
                    visible: true,
                    form: { userId },
                });
            },
            async handleAdd() {
                Object.assign(dialogConfig, {
                    title: '新增用户信息',
                    type: 'add',
                    rowFieldSize: 2,
                    visible: true,
                    form: {},
                });
            },
            async handleEdit(row) {
                Object.assign(dialogConfig, {
                    title: '修改用户信息',
                    type: 'edit',
                    rowFieldSize: 2,
                    visible: true,
                    form: { ...row, password: '' },
                });
            },
            handleDelete(row) {
                ElMessageBox.confirm(`是否删除【${row.userName}】`, '温馨提示').then(() => {
                    axios.delete(`/user/${row.userId}`).then(() => {
                        ElMessage({ type: 'success', message: '删除成功' });
                        sibTableRef.value.getTableData();
                    });
                }).catch(() => {});
            },
            handleDownload() {
                isLoading.value = true;
                axios.post('/user/importTemplate', { responseType: 'blob' }).then(res => {
                    window.SIB.download(res, `user_template_${new Date().getTime()}.xlsx`);
                    ElMessage({ type: 'success', message: '下载成功' });
                }).finally(() => {
                    isLoading.value = false;
                });
            },
            handleExport() {
                isLoading.value = true;
                axios.post('/user/export', sibTableRef.value.searchParams || {}, { responseType: 'blob' }).then(res => {
                    window.SIB.download(res, `user_${new Date().getTime()}.xlsx`);
                    ElMessage({ type: 'success', message: '导出成功' });
                }).finally(() => {
                    isLoading.value = false;
                });
            },
            handleSubmit(form, cb) {
                if (dialogConfig.type === 'reset') {
                    axios.put('/user/resetPwd', form).then(() => {
                        dialogConfig.visible = false;
                        dialogConfig.form = {};
                        sibTableRef.value.getTableData();
                        ElMessage({ type: 'success', message: `修改成功！新密码：${form.password}` });
                    }).finally(cb);
                    return;
                }
                const method = dialogConfig.type === 'edit' ? 'put' : 'post';
                const formData = new FormData();
                formData.append('user', new Blob([JSON.stringify(form)], { type: 'application/json' }));
                axios[method]('/user', formData).then(() => {
                    dialogConfig.visible = false;
                    dialogConfig.form = {};
                    sibTableRef.value.getTableData();
                }).finally(cb);
            },
        };
    },
};
</script>

<style lang="scss">
.system-user {
    display: flex;
    .sib-table-operate {
        display: flex;
        .sib-item__upload {
            display: inline-block;
            width: auto;
            margin: 0 10px;
        }
    }
    .sib-tree {
        width: 200px;
        height: 100%;
        margin-right: 10px;
        .sib-tree__header {
            .el-input {
                padding-top: 0;
            }
        }
    }
    .sib-table {
        width: calc(100% - 210px);
        height: 100%;
    }
}
</style>
